package ntu.sna;

import edu.uci.ics.jung.graph.Graph;

public class AlphaCalculator<V,E> {
	private Graph<V, E> g;
	private int maxDegree;
	private int minDegree;
	private double KL_Distance;
	
	// constructor
	public AlphaCalculator(Graph<V, E> g , int maxDegree , int minDegree){
		this.g = g; 
		this.maxDegree = maxDegree; 
		this.minDegree = minDegree; 
	}	
	
	public double run(){
		double alpha = 0 ; 
		
		int[] numOfSameDegree = new int[maxDegree+1];
		for(int i = 0 ; i < maxDegree+1 ; i++){
			numOfSameDegree[i] = 0;
		}
		
		for(V v : g.getVertices()){
			numOfSameDegree[g.degree(v)]++;
		}
		
		double n = 0;
		double tmp = 0 ;
	    
		for (int i = minDegree; i < maxDegree+1 ; i++ ){
			if(i >= minDegree && numOfSameDegree[i]>0 ){
				tmp += numOfSameDegree[i] * Math.log( (double)i / (double)minDegree );	
				n += numOfSameDegree[i];
			}
		}
		System.out.println("alpha:"+alpha);
		System.out.println("n="+n);
		tmp = (double)1/tmp ;
		alpha = tmp * n + 1;
		
		// calculate KL_Distance
		// p(x) = (alpha-1)/Xmin * (X/Xmin)^(-alpha)
		double compareDistribution[] = new double[maxDegree+1];
		for(int i = 0 ; i < maxDegree+1 ; i++){
			if(numOfSameDegree[i] !=0 ){
				compareDistribution[i] = ((alpha-1)/(double)minDegree * Math.pow(((double)i/minDegree), alpha*(-1)));
			}else{
				compareDistribution[i] = 0 ;
			}
		}
		
		KL_Distance = 0;
		for (int i = minDegree; i < maxDegree+1 ; i++ ){
			if(compareDistribution[i] != 0 && numOfSameDegree[i] != 0){
				KL_Distance += Math.log10((numOfSameDegree[i]/n)/compareDistribution[i]) * (numOfSameDegree[i]/n);
				KL_Distance += Math.log10(compareDistribution[i]/(numOfSameDegree[i]/n)) * compareDistribution[i];
			}
		}
        	
		return alpha ;
	}
	
	public double getKL_Distance(){
		return KL_Distance;
	}
}
